package de.dhbw.karlsruhe.picsim.model.timer;

import de.dhbw.karlsruhe.picsim.model.cpu.ReadOnlyFile;
import de.dhbw.karlsruhe.picsim.model.io.External;
import de.dhbw.karlsruhe.picsim.util.Bits;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jetbrains.annotations.NotNull;

/**
 * Created by IntelliJ IDEA.
 * User: goesen
 * Date: Apr 27, 2010
 * Time: 4:05:19 PM
 */
final class ExternalClock implements External.ExternalListener {
    private final ReadOnlyFile option;
    private final Timer timer;
    private static final Log log = LogFactory.getLog(ExternalClock.class);

    ExternalClock(final ReadOnlyFile option, final Timer timer) {
        this.option = option;
        this.timer = timer;
    }

    @Override
    public void handlePortAChange(@NotNull final Bits oldValue, @NotNull final Bits newValue) {
/*
         P25.
        Timer mode is selected by clearing the T0CS bit
                (OPTION<5>). In timer mode, the Timer0 module
        (Figure 6-1) will increment every instruction cycle
                (without prescaler).
                ...
                Counter mode is selected by setting the T0CS bit
        (OPTION<5>). In this mode TMR0 will increment either
        on every rising or falling edge of pin RA4/T0CKI. The
        incrementing edge is determined by the T0 source
        edge select bit, T0SE (OPTION<4>). Clearing bit T0SE
        selects the rising edge. Restrictions on the external

*/
        //nur wenn sich RA4 auch geändert hat
        final boolean ra4 = newValue.isSet(4);
        if (ra4 != oldValue.isSet(4)) {

            //nur wenn nicht im Timer mode
            if (isExternalClockMode(option)) {
                //nur wenn auch die richtige Flanke (rauf oder runter) kommt
                if (option.getData().isSet(4) ^ ra4) {
                    //erhöhe den timer oder prescaler oder was auch immer
                    log.debug("increment by external clock");
                    timer.increment();
                }

            }
        }


    }

    @Override
    public void handlePortBChange(@NotNull final Bits oldValue, @NotNull final Bits newValue) {
        //dont care

    }

    static boolean isExternalClockMode(final ReadOnlyFile option) {
        return option.getData().isSet(5);
    }
}
